%option noyywrap

%{
#include "interface.h"
#include <stdlib.h>
#include <string.h>
#define COMMENT 0
#define NOCOMMENT 1

int	nCommentFlag = NOCOMMENT;
int nLineNo = 1;
%}


%%

"/*"	{
			fprintf(yyout, "<FONT COLOR=\"#008000\">");
			fprintf(yyout, "%s", yytext);
			nCommentFlag = COMMENT;
		}

"*/"	{
			fprintf(yyout, "%s", yytext);
			fprintf(yyout, "</FONT>");
			nCommentFlag = NOCOMMENT;
		}

\"[^\n"]*\" {
				if(nCommentFlag == NOCOMMENT)
				{
					fprintf(yyout, "<FONT COLOR=\"#ff0000\">");
					fprintf(yyout, "%s", yytext);
					fprintf(yyout, "</FONT>");
				}
				else
					ECHO;
			}

"//".*		{
				if(nCommentFlag == NOCOMMENT)
				{
					fprintf(yyout, "<FONT COLOR=\"#008000\">");
					fprintf(yyout, "%s", yytext);
					fprintf(yyout, "</FONT>");
				}
				else
				{
					int lineLen = strlen(yytext);
					if (('*' == yytext[lineLen - 2]) && ('/' == yytext[lineLen - 1]))
					{
						fprintf(yyout, "%s", yytext);
						fprintf(yyout, "</FONT>");
						nCommentFlag = NOCOMMENT;
					}
				}
			}

\n			{
					int nCovered = 0;
					if(IsLineCovered(nLineNo))
					{
						fprintf(yyout, "</span>");
					}
					fprintf(yyout, "\n");
					nCovered = IsLineCovered(nLineNo + 1);
					if(nCovered == 2)
					{
						fprintf(yyout, "<span class='covered'>");
					}
					else if(nCovered == 1)
					{
						fprintf(yyout, "<span class='partiallycovered'>");
					}

					fprintf(yyout, "<a class='lineno'>%d.</a>\t", ++nLineNo);
			}

^[ ]+		{
				int i;
				for(i = 0; i < yyleng; ++i)
					fprintf(yyout, "&nbsp;");
				fprintf(yyout, " ");
			}

\t			{
				fprintf(yyout, "&nbsp;&nbsp;&nbsp;&nbsp; ");
			}

"<"		{
			fprintf(yyout, "&lt;");
		}

">"		{
			fprintf(yyout, "&gt;");
		}
		
"&"		{
			fprintf(yyout, "&amp;");
		}


"auto"				|
"const"				|
"double"			|
"float"				|
"int"				|
"short"				|
"struct"			|
"unsigned"			|
"break"				|
"continue"			|
"else"				|
"for"				|
"long"				|
"signed"			|
"switch"			|
"void"				|
"case"				|
"default"			|
"enum"				|
"goto"				|
"register"			|
"sizeof"			|
"typedef"			|
"volatile"			|
"char"				|
"do"				|
"extern"			|
"if"				|
"return"			|
"static"			|
"union"				|
"while"				|
"asm"				|
"dynamic_cast"		|
"namespace"			|
"reinterpret_cast"	|
"try"				|
"bool"				|
"explicit"			|
"new"				|
"static_cast"		|
"typeid"			|
"catch"				|
"false"				|
"operator"			|
"template"			|
"typename"			|
"class"				|
"friend"			|
"private"			|
"this"				|
"using"				|
"const_cast"		|
"inline"			|
"public"			|
"throw"				|
"virtual"			|
"delete"			|
"mutable"			|
"protected"			|
"true"				|
"#include"			|
"#define"			|
"#undef"			|
"#pragma"			|
"#if"				|
"#ifdef"			|
"#ifndef"			|
"#endif"			|
"#import"			|
"wchar_t"	{
				if(nCommentFlag == NOCOMMENT)
				{
					fprintf(yyout, "<FONT COLOR=\"#0000ff\">");
					fprintf(yyout, "%s", yytext);
					fprintf(yyout, "</FONT>");
				}
				else
					ECHO;
			}

[a-z|_|0-9]+	{
			ECHO;
		}
%%
void printFirstLineNo()
{
	int nCovered = IsLineCovered(nLineNo);
	if(nCovered == 2)
	{
		fprintf(yyout, "<span class='covered'>");
	}
	else if(nCovered == 1)
	{
		fprintf(yyout, "<span class='partiallycovered'>");
	}
	
	fprintf(yyout, "<a class='lineno'>%d.</a>\t", nLineNo);
}

int parseFile(const char* szInFileName, const char* szOutFileName, int full)
{
	nLineNo = 1;
	yyin = fopen(szInFileName, "r" );
	if(yyin == NULL)
	{
		printf("Can not open input file %s\n", szInFileName);
		return 0;
	}

	yyout = fopen(szOutFileName, "w");
	if(yyout == NULL)
	{
		printf("Can not open output file %s\n", szOutFileName);
		return 0;
	}

	if (full)
	{
		fprintf(yyout, "%s", "<HTML>\n<HEAD>\n<style>\n	.covered{background-Color:#E0EDFD;}\n .partiallycovered{background-Color:#FFEFCE;}\n pre{font-family:Verdana;font-size:10pt;}\n .lineno{width:50px; text-align: center; line-height:18px; border-right:3px solid #33FF00;background-Color:#EEEEEE;}\n</style>\n</HEAD>\n<BODY>\n<CODE>\n<PRE>\n");
		printFirstLineNo();
		yylex();
		fprintf(yyout, "%s", "</PRE>\n</CODE>\n</BODY>\n</HTML>");
	}
	else
	{
		fprintf(yyout, "%s", "<CODE>\n<PRE>\n");
		printFirstLineNo();
		yylex();
		fprintf(yyout, "%s", "</PRE>\n</CODE>\n");
	}

	fclose(yyin);
	fclose(yyout);
	
	return 1;
}


void parseText(char* szText, char** ppOutText)
{
	char* szFileInputName  = "cpp2htmltempfilein.txt";
	char* szFileOutputName = "cpp2htmltempfileout.txt";
	FILE* input            = NULL;
	FILE* output           = NULL;

	if ((NULL == szText) || (NULL == ppOutText))
	{
		return;
	}

	// Create a file and write the input text into it.
	input = fopen(szFileInputName, "w" );
	if (NULL == input)
	{
		return;
	}

	fprintf(input, "%s", szText);
	fclose(input);
	input = NULL;

	// Generate the output file.
	if (!parseFile(szFileInputName, szFileOutputName, 0))
	{
		return;
	}

	output = fopen(szFileOutputName, "r" );
	if (output != NULL)
	{
		*ppOutText = calloc(1, sizeof(char) * (4* strlen(szText) + 1));
		if (*ppOutText != NULL)
		{
			int i = 0;
			int c = 0;
			while ((c = fgetc(output)) != EOF)
			{
				(*ppOutText)[i] = c;
				i++;
			}
		}
		
		fclose(output);
		output = NULL;
	}
	
	// Remove temporary files.
	remove(szFileInputName);
	remove(szFileOutputName);
}
